// ==UserScript== // @name TikTok 小助手 // @namespace http://tampermonkey.net/ // @version 5.19 // @description 获取 ttk 数据! // @author // @match https://www.tiktok.com/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceText // @grant GM_addStyle // @icon https://iili.io/dy5xjOg.jpg // @require https://code.jquery.com/jquery-3.6.0.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/toastify-js/1.12.0/toastify.min.js // @resource TOASTIFY_CSS https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css // ==/UserScript== (function() { 'use strict'; // 加载 Toastify.js 的 CSS const toastifyCSS = GM_getResourceText('TOASTIFY_CSS'); GM_addStyle(toastifyCSS); // 现在可以使用 Toastify.js 了 let currentUrl = window.location.href; let retryCount = 0; let dataDisplayed = false; // 新增标志位 // 获取设置值,默认值为 false let autoShowDataPanel = GM_getValue('autoShowDataPanel', false); // 在脚本菜单中添加选项以设置是否自动弹出数据面板 GM_registerMenuCommand('切换自动弹出数据面板', () => { autoShowDataPanel = !autoShowDataPanel; GM_setValue('autoShowDataPanel', autoShowDataPanel); alert(`自动弹出数据面板已${autoShowDataPanel ? '启用' : '禁用'}`); }); // 注入按钮样式到页面 function injectButtonStyles() { const styleElement = document.createElement('style'); styleElement.type = 'text/css'; styleElement.textContent = ` .button-87 { margin: 0px; padding: 10px 10px; text-align: center; text-transform: uppercase; transition: 0.5s; background-size: 100% auto; color: white; border-radius: 10px; display: block; border: 0px; font-weight: 700; box-shadow: 0px 0px 14px -7px #f09819; background-image: linear-gradient(45deg, #FF512F 0%, #F09819 51%, #FF512F 100%); cursor: pointer; user-select: none; -webkit-user-select: none; touch-action: manipulation; } .button-87:hover { background-position: right center; /* change the direction of the change here */ color: #fff; text-decoration: none; } .button-87:active { transform: scale(0.95); } `; document.head.appendChild(styleElement); } // 创建用于显示数据面板的按钮 function createButton(parsedData) { const existingButton = document.querySelector('#tiktokDataButton'); if (existingButton) { existingButton.remove(); } // 创建新的按钮,使用您提供的样式类 const button = document.createElement('button'); button.id = 'tiktokDataButton'; button.className = 'button-87'; button.innerHTML = '🤓'; button.style.position = 'fixed'; button.style.top = '10px'; button.style.right = '350px'; button.style.zIndex = '10001'; button.addEventListener('click', () => { toggleDataDisplay(parsedData); }); document.body.appendChild(button); console.log('Button created and appended to the page.'); createRefreshButton(); injectButtonStyles(); // 注入样式 } // 创建手动刷新数据的按钮 function createRefreshButton() { const existingRefreshButton = document.querySelector('#tiktokRefreshButton'); if (existingRefreshButton) { existingRefreshButton.remove(); } const refreshButton = document.createElement('button'); refreshButton.id = 'tiktokRefreshButton'; refreshButton.className = 'button-87'; refreshButton.innerHTML = '🔄'; refreshButton.style.position = 'fixed'; refreshButton.style.top = '10px'; refreshButton.style.right = '400px'; refreshButton.style.zIndex = '10001'; refreshButton.addEventListener('click', () => { console.log('Manual refresh button clicked.'); retryCount = 0; currentUrl = window.location.href; dataDisplayed = false; // 重置标志位 extractStats(true); }); document.body.appendChild(refreshButton); } // 切换数据面板的显示和隐藏 function toggleDataDisplay(parsedData) { console.log('toggleDataDisplay called'); let dataContainer = document.querySelector('#tiktokDataContainer'); if (dataContainer) { dataContainer.style.transform = 'translateX(100%)'; dataContainer.style.opacity = '0'; setTimeout(() => { dataContainer.remove(); }, 500); return; } dataContainer = document.createElement('div'); dataContainer.id = 'tiktokDataContainer'; dataContainer.style.transition = 'transform 0.5s ease-in-out, opacity 0.5s ease-in-out'; dataContainer.style.transform = 'translateX(100%)'; dataContainer.style.opacity = '0'; dataContainer.style.position = 'fixed'; dataContainer.style.top = '60px'; dataContainer.style.right = '20px'; dataContainer.style.width = '300px'; dataContainer.style.maxHeight = '400px'; dataContainer.style.overflowY = 'auto'; dataContainer.style.backgroundColor = '#ffffff'; dataContainer.style.border = '1px solid #ccc'; dataContainer.style.borderRadius = '8px'; dataContainer.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.1)'; dataContainer.style.padding = '15px'; dataContainer.style.zIndex = '10000'; const title = document.createElement('h2'); title.textContent = '🎉 好!发现了'; title.style.color = '#000000'; title.style.marginBottom = '10px'; dataContainer.appendChild(title); createJsonElement(parsedData, dataContainer); document.body.appendChild(dataContainer); setTimeout(() => { dataContainer.style.transform = 'translateX(0)'; dataContainer.style.opacity = '1'; }, 10); } // 创建用于显示数据的元素 function createJsonElement(data, container) { const fields = ['diggCount', 'playCount', 'commentCount', 'shareCount', 'collectCount', 'createTime']; // 提取账户名,去掉 @ 符号 const accountName = window.location.pathname.split('/')[1].replace('@', ''); // Base64 编码的复制图标 const base64CopyIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAYUlEQVR4nGNgGE7Am4GB4QkDA8N/MjFB8JgCw/8TNp4EheQCulvgTWacgILakxgLKImTR8RYAOP7kIhxBvWoBT6jQeQzmor+0zqjoYOhb8Fjahd26MCTTEtAhnsQY8HQAABVctFxfxXV5QAAAABJRU5ErkJggg=="; // 创建账户名和复制图标 const accountRow = document.createElement('div'); accountRow.style.display = 'flex'; accountRow.style.alignItems = 'center'; accountRow.style.marginBottom = '5px'; const accountNameElement = document.createElement('div'); accountNameElement.style.fontWeight = 'bold'; accountNameElement.style.fontSize = '20px'; accountNameElement.textContent = `${accountName}`; const copyAccountIcon = document.createElement('img'); copyAccountIcon.src = base64CopyIcon; copyAccountIcon.style.cursor = 'pointer'; copyAccountIcon.style.width = '20px'; copyAccountIcon.style.marginLeft = '10px'; copyAccountIcon.addEventListener('click', (event) => { event.preventDefault(); navigator.clipboard.writeText(accountName).then(() => { showNotification('已复制到剪贴板: ' + accountName); }).catch(err => { console.error('复制失败: ', err); }); }); accountRow.appendChild(accountNameElement); accountRow.appendChild(copyAccountIcon); container.appendChild(accountRow); // 创建粉丝数和复制图标 const followerCountRow = document.createElement('div'); followerCountRow.style.display = 'flex'; followerCountRow.style.alignItems = 'center'; followerCountRow.style.marginBottom = '10px'; const followerCountText = document.createElement('div'); followerCountText.textContent = `粉丝数: ${data.followerCount || '未知'}`; const copyFollowerIcon = document.createElement('img'); copyFollowerIcon.src = base64CopyIcon; copyFollowerIcon.style.cursor = 'pointer'; copyFollowerIcon.style.width = '20px'; copyFollowerIcon.style.marginLeft = '10px'; copyFollowerIcon.addEventListener('click', (event) => { event.preventDefault(); navigator.clipboard.writeText(data.followerCount).then(() => { showNotification('已复制到剪贴板: ' + followerCountText.textContent); }).catch(err => { console.error('复制失败: ', err); }); }); followerCountRow.appendChild(followerCountText); followerCountRow.appendChild(copyFollowerIcon); container.appendChild(followerCountRow); // 创建其他统计信息 fields.forEach(field => { if (data.hasOwnProperty(field)) { if (field === 'createTime' && data[field] === 0) { return; // 如果 createTime 为 0,则跳过 } const item = document.createElement('div'); item.style.marginBottom = '10px'; item.style.display = 'flex'; item.style.alignItems = 'center'; let text = ''; if (field === 'diggCount') { text = `点赞数: ${data[field]}`; } else if (field === 'playCount') { text = `播放数: ${data[field]}`; } else if (field === 'commentCount') { text = `评论数: ${data[field]}`; } else if (field === 'shareCount') { text = `分享数: ${data[field]}`; } else if (field === 'collectCount') { text = `收藏数: ${data[field]}`; } else if (field === 'createTime') { const date = new Date(data[field] * 1000); text = `创建时间: ${date.toLocaleString()}`; } const textElement = document.createElement('span'); textElement.textContent = text; textElement.style.color = '#000000'; item.appendChild(textElement); const copyButtonIcon = document.createElement('img'); copyButtonIcon.src = base64CopyIcon; copyButtonIcon.style.cursor = 'pointer'; copyButtonIcon.style.width = '20px'; copyButtonIcon.style.marginLeft = '10px'; copyButtonIcon.addEventListener('click', (event) => { event.preventDefault(); if (field === 'createTime') { const date = new Date(data[field] * 1000); const formattedDate = date.toISOString().slice(0, 19).replace('T', ' '); navigator.clipboard.writeText(formattedDate).then(() => { showNotification('已复制到剪贴板: ' + formattedDate); }).catch(err => { console.error('复制失败: ', err); }); } else { navigator.clipboard.writeText(data[field]).then(() => { showNotification('已复制到剪贴板: ' + data[field]); }).catch(err => { console.error('复制失败: ', err); }); } }); item.appendChild(copyButtonIcon); container.appendChild(item); } }); } // 提取视频统计信息 function extractStats(isManual = false) { fetch(window.location.href) .then(response => response.text()) .then(responseText => { const scriptMatch = responseText.match(/